﻿//Copyright (C) <2013>  <jonathan cleeve norton> All Rights Reserved 
//Contact jon.norton@fin-plus.co.uk website <http://www.fin-plus.co.uk/>
using System;
using System.Collections.ObjectModel;
using System.Windows;
using System.Reflection;
using System.IO;
using System.ComponentModel;
using System.Diagnostics;
using FinPlusCommon;
using Messaging2;
using log = Logger.Logger;
using u = FinPlusUtility.Utility;

namespace FinPlusWPFControls
{
    public partial class FinPlusMontage : FinPlusControl
    {
        public override string[] States { get { return new string[] { "Height", "Width", "Left", "Top" }; } }
        public override string[] TestStates { get { return new string[] { "TestString", "ColumnsCount", "ItemsCount", "IsValid" }; } }

        public int ColumnsCount { get { return dataGrid.Columns.Count; } }
        public int ItemsCount { get { return dataGrid.Items.Count; } }

        private readonly Clients _clients;
        private readonly ITransport _tran;

        //construct
        public FinPlusMontage(string configFolder, string configName, string clientExecutable)
        {
            InitializeComponent();
            _clients = new Clients();
            u.Env env;
            var config = u.ConfigXml(u.GetAssemblyPath(Assembly.GetEntryAssembly()) + configName + ".config", out env);
            _tran = new Transport(config["localmessagingsettings"]["address"], int.Parse(config["localmessagingsettings"]["port"]));
            _tran.Listener.MessageRecieved += OnClose;
            _tran.Listen("OnClose");
         
            LoadClients(configFolder, clientExecutable);

            IsValid = true;
        }

        //common control interface
        public override void CmdExecute(IFunction command)
        {
            try
            {
                CmdCapture(command);

                switch ((Cmds)Enum.Parse(typeof(Cmds), command.Name, true))
                {
                    case Cmds.Open: OpenClient(); break;
                    case Cmds.Home: ((Client)dataGrid.SelectedItem).Home(); break;
                    case Cmds.Save: ((Client)dataGrid.SelectedItem).Save(); break;
                    case Cmds.Minimize: ((Client)dataGrid.SelectedItem).Minimize(); break;
                    case Cmds.Maximize: ((Client)dataGrid.SelectedItem).Maximize(); break;
                    case Cmds.Close: CloseClient(); break;
                    case Cmds.OnClose: OnCloseClient(command["Tag"].ToString()); break;
                    default: throw new Exception(string.Format("event not recognised {0}", command.Name));
                }
            }
            catch (CmdExecuteException e)
            {
                IsValid = log.Log(Logger.Level.Warning, Id, Config, e.Message, e);
            }
        }

        public override void Dispose()
        {
            _clients.Close();
        }

        //private
        private void LoadClients(string configFolder, string clientExecutable)
        {
            try
            {
                var path = u.GetAssemblyPath(Assembly.GetExecutingAssembly());
                _clients.GetClients(path + configFolder, path + clientExecutable, Env, _tran);
                dataGrid.ItemsSource = _clients;
            }
            catch (Exception e)
            {
                log.Log(Logger.Level.Error, Id, Config, e.Message, e);
            }
        }

        private void OpenClient()
        {
            var client = (Client)dataGrid.SelectedItem;

            if (client.IsOpen)
                client.Close();
            else
                client.Open();
        }

        private void CloseClient()
        {
            var client = (Client)dataGrid.SelectedItem;

            if (client.IsOpen)
               client.Close();
        }

        private void OnCloseClient(string guid)
        {
            foreach (var client in _clients)
                client.OnClose(guid);
        }

        //cmds
        private enum Cmds { Open, Home, Save, Minimize, Maximize, Close, OnClose }

        //events
        private void OnClose(object s, EventArgs a){ CmdRouter(Cmds.OnClose.ToString(), ((MessageEventArgs)a).Message.Value.ToString());
        }
    }

    internal class Clients : ObservableCollection<Client>
    {
        public void GetClients(string configsPath, string client, u.Env env, ITransport tran)
        {
            var dir = new DirectoryInfo(configsPath);
            foreach (var clientIOFile in dir.GetFiles("*.view"))
                this.Add(new Client(clientIOFile, client, env, tran));
        }

        public void Close()
        {
            try
            {
                foreach (var client in this)
                    client.Close();
            }
            catch (Exception e)
            {
                log.Log(Logger.Level.Warning, e.Message, e);
            }
        }
    }

    internal class Client : INotifyPropertyChanged
    {
        public string Name { get; set; }
        public bool IsOpen { get { return _isOpen; } set { _isOpen = value; NotifyPropertyChanged("IsOpen"); } }
        public event PropertyChangedEventHandler PropertyChanged;

        private ITransport _tran;
        private FileInfo _fileInfo;
        private Process _process;
        private u.Env _env;
        private string _configPath, _client, _guid;
        private bool _isOpen;

        //public
        public Client(FileInfo fileInfo, string client, u.Env env, ITransport tran)
        {
            _fileInfo = fileInfo;
            _client = client;
            _env = env;
            _tran = tran;
            _configPath = fileInfo.FullName.Replace(".view", "");
            _guid = u.Guid();
            Name = fileInfo.Name.Split('.')[0];
        }
       
        public void Open()
        {
            try
            {
                _process = FinPlusWindow.OpenWindow(_configPath, Name, _guid, "NA");
                IsOpen = true;
            }
            catch (Exception e)
            {
                log.Log(Logger.Level.Warning, e.Message, e);
            }
        }

        public void Close()
        {
            if (_tran != null && IsOpen)
                _tran.Publish(new Message(Cmds.Close.ToString(), _guid));
            IsOpen = false;
        }

        public void OnClose(string guid)
        {
            if (!_guid.Equals(guid)) return;
       
            IsOpen = false;
        }

        public void Home()
        {
            if (_tran != null && IsOpen)
                _tran.Publish(new Message(Cmds.Home.ToString(), _guid));
        }

        public void Save()
        {
            if (_tran != null && IsOpen)
                _tran.Publish(new Message(Cmds.Save.ToString(), _guid)); 
        }

        public void Minimize()
        {
            if (_tran != null && IsOpen)
                _tran.Publish(new Message(Cmds.Minimize.ToString(), _guid));
        }

        public void Maximize()
        {
            if (_tran != null && IsOpen)
                _tran.Publish(new Message(Cmds.Maximize.ToString(), _guid));
        }

        //private
        private void NotifyPropertyChanged(string propName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propName));
        }

        private enum Cmds { Close, Home, Save, Minimize, Maximize }
    }
}
